icon-theme: Fix deadlock in GktIconTheme dispose
authorAlexander Larsson <alexl@redhat.com>
Wed, 22 Apr 2020 12:20:33 +0000 (14:20 +0200)
committerMatthias Clasen <mclasen@redhat.com>
Wed, 22 Apr 2020 16:20:57 +0000 (12:20 -0400)
When freeing the display GtkIconTheme and that was the last owner we
ran into a deadlock, because we unref the "next-to-last" ref inside a
gtk_icon_theme_ref_aquire/release() pair, which makes the final unref
to happen in the release(), while the ref lock still was held.
The unref triggers dispose which tries to NULL out the ref, but that then
deadlocks on the mutex being held by the caller already.

We fix this by moving the release unref outside the lock. This is safe
because refcounts are atomic, and we *do* own the ref.

gtk/gtkicontheme.c

index c8e5eaaa50faba03adecac54d62c7e777016cefc..cce4706c959debd5e9dd03703bf23a408bf5d49f 100644 (file)
@@ -549,9 +549,16 @@ gtk_icon_theme_ref_aquire (GtkIconThemeRef *ref)
 static void
 gtk_icon_theme_ref_release (GtkIconThemeRef *ref)
 {
-  if (ref->theme)
-    g_object_unref (ref->theme);
+  GtkIconTheme *theme;
+
+  /* Get a pointer to the theme, becuse when we unlock it could become NULLed by dispose, this pointer still owns a ref */
+  theme = ref->theme;
   g_mutex_unlock (&ref->lock);
+
+  /* Then unref outside the lock, because otherwis if this is the last ref the dispose handler would deadlock trying to NULL ref->theme */
+  if (theme)
+    g_object_unref (theme);
+
 }
 
 static void